package com.fqgj.xjd.user.service.impl;

import com.fqgj.base.services.redis.TimeConsts;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.DateUtil;
import com.fqgj.exception.common.ApiErrorException;
import com.fqgj.exception.enums.BasicErrorCodeEnum;
import com.fqgj.xjd.user.client.*;
import com.fqgj.xjd.user.client.enums.UserQuotaEnum;
import com.fqgj.xjd.user.client.request.*;
import com.fqgj.xjd.user.client.response.*;
import com.fqgj.xjd.user.common.constants.UserProfileConsts;
import com.fqgj.xjd.user.common.enums.UserErrorCodeEnum;
import com.fqgj.xjd.user.dao.UserContactCarrierDao;
import com.fqgj.xjd.user.dao.UserQuotaDao;
import com.fqgj.xjd.user.dao.UserQuotaHistoryDao;
import com.fqgj.xjd.user.entity.UserContactCarrierEntity;
import com.fqgj.xjd.user.entity.UserQuotaEntity;
import com.fqgj.xjd.user.entity.UserQuotaHistoryEntity;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.fqgj.xjd.user.client.enums.UserQuotaEvaluateEnum.*;

/**
 * Created by scrack on 2017/7/22.
 */
@Service("userQuotaService")
public class UserQuotaServiceImpl implements UserQuotaService {

    @Autowired
    private UserQuotaDao userQuotaDao;
    @Autowired
    private UserContactCarrierDao userContactCarrierDao;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserContactService userContactService;
    @Autowired
    private UserBankService userBankService;
    @Autowired
    private UserAuthService userAuthService;
    @Autowired
    private UserQuotaHistoryDao userQuotaHistoryDao;

    @Override
    public Response<UserQuotaResponse> getQuota(String userCode, String categoryCode) {
        Map<String, Object> map = new HashMap<>();
        map.put("userCode", userCode);
        map.put("categoryCode", categoryCode);
        UserQuotaEntity userQuotaEntity = userQuotaDao.getQutoaByuserCodeAndCategory(map);
        return Response.ok().putData(packageUserQuotaResponse(userQuotaEntity));
    }

    private UserQuotaResponse packageUserQuotaResponse(UserQuotaEntity userQuotaEntity){
        UserQuotaResponse userQuotaResponse = new UserQuotaResponse();
        if (userQuotaEntity != null && userQuotaEntity.getStatus().equals(UserQuotaEnum.PASS.getType())) {
            userQuotaResponse.setUserCode(userQuotaEntity.getUserCode());
            userQuotaResponse.setQuota(userQuotaEntity.getTotalQuota());
            userQuotaResponse.setCategoryCode(userQuotaEntity.getCategoryCode());
            userQuotaResponse.setModifiedTime(userQuotaEntity.getGmtModified());
            userQuotaResponse.setUserQuotaEnum(UserQuotaEnum.getEnumByType(userQuotaEntity.getStatus()));
            userQuotaResponse.setRiskLevel(userQuotaEntity.getRiskLevel());
        } else {
            userQuotaResponse.setUserQuotaEnum(UserQuotaEnum.NOT_EVALUATED);
        }
        return userQuotaResponse;
    }

    @Override
    public Response<List<UserQuotaResponse>> selectQuotaByUserCodes(List<String> userCodes) {
        if(CollectionUtils.isEmpty(userCodes)){
            return Response.error(BasicErrorCodeEnum.PARAM_NOT_COMPLETE, "userCodes can not be empty");
        }
        List<UserQuotaEntity> userQuotaEntities = userQuotaDao.getAllQuotaByUserCodes(userCodes);
        List<UserQuotaResponse> userQuotas = Lists.newArrayList();
        for(UserQuotaEntity entity : userQuotaEntities){
            userQuotas.add(packageUserQuotaResponse(entity));
        }
        return Response.ok().putData(userQuotas);
    }

    @Override
    public Response<Boolean> saveQuotaResult(UserQuotaRequest userQuotaRequest) {
        //获取额度
        Map<String, Object> map = new HashMap<>();
        map.put("userCode", userQuotaRequest.getUserCode());
        map.put("categoryCode", userQuotaRequest.getCategoryCode());
        UserQuotaEntity oldUserQuotaEntity = userQuotaDao.getQutoaByuserCodeAndCategory(map);

        UserQuotaEntity userQuotaEntity = new UserQuotaEntity();
        userQuotaEntity.setUserCode(userQuotaRequest.getUserCode());
        userQuotaEntity.setCategoryCode(userQuotaRequest.getCategoryCode());
        userQuotaEntity.setStatus(userQuotaRequest.getQuotaEnum().getType());
        userQuotaEntity.setTotalQuota(userQuotaRequest.getAmount());
        userQuotaEntity.setRiskLevel(userQuotaRequest.getRiskLevel());
        userQuotaEntity.setDeleted(false);
        //保存额度
        userQuotaEntity.setAvailableQuota(userQuotaRequest.getAmount());
        if (null != oldUserQuotaEntity) {
            userQuotaDao.updateByUserCodyAndCategory(userQuotaEntity);
        } else {
            userQuotaDao.saveQuota(userQuotaEntity);
        }
        //保存额度变化流水
        UserQuotaHistoryEntity userQuotaHistoryEntity = new UserQuotaHistoryEntity();
        userQuotaHistoryEntity.setUserCode(userQuotaEntity.getUserCode());
        userQuotaHistoryEntity.setCategoryCode(userQuotaEntity.getCategoryCode());
        userQuotaHistoryEntity.setOldQuota(null != oldUserQuotaEntity ? new BigDecimal(oldUserQuotaEntity.getTotalQuota()) : BigDecimal.ZERO);
        userQuotaHistoryEntity.setNewQuota(new BigDecimal(userQuotaRequest.getAmount()));
        userQuotaHistoryEntity.setAdjustQuota(userQuotaHistoryEntity.getNewQuota().subtract(userQuotaHistoryEntity.getOldQuota()).doubleValue());
        userQuotaHistoryEntity.setType(getQuotaType(userQuotaHistoryEntity.getAdjustQuota()));
        userQuotaHistoryEntity.setCreatedBy("system");
        userQuotaHistoryEntity.setRemark("system");
        userQuotaHistoryDao.insert(userQuotaHistoryEntity);
        return Response.ok().putData(true);
    }

    /**
     * 获取 额度调整类型
     * @see com.fqgj.xjd.user.client.enums.UserQuotaEvaluateEnum
     */
    private Integer getQuotaType(double adjustQuota) {
        if (adjustQuota > 0) {
            return PROMOTE_QUOTA.getType();
        } else if (adjustQuota < 0) {
            return REDUCE_QUOTA.getType();
        } else {
            return KEEP_QUOTA.getType();
        }
    }

    /**
     * 评估额度
     * @param userCode
     * @param productCategory
     * @return
     */
    @Override
    public Response<Boolean> evaluateQuota(String userCode, String productCategory) {
        //1、获取用户信息
        Response<UserInfo> rs = userInfoService.getUserInfoByUserCode(userCode);
        if (!rs.isSuccess()) {
            return Response.error(UserErrorCodeEnum.USER_NOT_EXIST);
        }
        UserInfo userInfo = rs.getData();
        User user = userInfo.getUser();
        Response<UserSocialContact> rs2 = userContactService.getUserSocialContactByUserCode(userCode);
        if (!rs.isSuccess()) {
            return Response.error(UserErrorCodeEnum.USER_NOT_EXIST);
        }
        //2、获取联系人信息
        UserSocialContact socialContact = rs2.getData();
        if (!fourStepActionComplete(userInfo, socialContact)) {
            return Response.error(UserErrorCodeEnum.NO_CONTACT_INFO);
        }
        //3、获取额度信息
        Response<UserQuotaResponse> quotaRs = getQuota(userCode, productCategory);
        if (!rs.isSuccess()) {
            return Response.error(UserErrorCodeEnum.QUERY_QUOTA_ERROR);
        }
        UserQuotaResponse userQuota = quotaRs.getData();
        UserQuotaEnum userQuotaEnum = userQuota.getUserQuotaEnum();

        if (UserQuotaEnum.PASS.equals(userQuotaEnum)) {
            //  已获得额度不进行重新评估
            return Response.error(UserErrorCodeEnum.EVALUATE_QUOTA_ALREADY);
        }
        if (userQuotaEnum != null
                && (userQuotaEnum.equals(UserQuotaEnum.CREDIT_SCORE_LACK) || userQuotaEnum.equals(UserQuotaEnum.NEED_WAIT_MONTH))
                && DateUtil.diffDateToSecond(new Date(), userQuota.getModifiedTime()) < TimeConsts.ONE_MONTH) {
            //  距上次未获得额度未超过三十个自然日，不进行重新评估
            return Response.error(UserErrorCodeEnum.EVALUATE_QUOTA_LESS_THEN_30DAYS);
        }
        //3、芝麻认证 实名认证校验
        /*if (!userZMCreditAuthorized(rs.getData().getUser())) {
            return Response.error(UserErrorCodeEnum.ZM_AUTH_ERROR);
        }*/
        Response<CreditAuthResponse> creditAuthResponseResponse = userAuthService.getCreditAuthInfoByUserCode(userCode);
        if (!creditAuthResponseResponse.isSuccess()) {
            return Response.error(UserErrorCodeEnum.USER_NOT_AUTHED);
        }
        //参数组装，调用风控评估额度
        // TODO: 2017/9/21 处理闪电周转,目前写死
        if (productCategory.equals("sdzzall") || productCategory.equals("xjdrall")) {
            UserQuotaRequest request = new UserQuotaRequest()
                    .setUserCode(userCode)
                    .setCategoryCode(productCategory)
                    .setAmount(5000D)
                    .setQuotaEnum(UserQuotaEnum.PASS);
            saveQuotaResult(request);
            return new Response<>().ok().putData(true);
        }

        UserContactCarrierEntity userContactCarrierEntity = userContactCarrierDao.selectByUserCode(userCode);
        if (userContactCarrierEntity == null) {
            return Response.error(UserErrorCodeEnum.CAN_NOT_EVALUATE_QUOTA, "Carrier does not exits");
        }

//        UserContactAddressBookEntity userContactAddressBookEntity = userContactAddressBookDao.selectByUserCode(userCode);
//        if (userContactAddressBookEntity == null) {
//            return Response.error(UserErrorCodeEnum.CAN_NOT_EVALUATE_QUOTA, "通讯录不存在");
//        }

        /*UserAuthZhimaEntity userAuthZhimaEntity = userAuthZhimaDao.selectUserAuthZhimaByUserCode(userCode);
        if (userAuthZhimaEntity == null) {
            return Response.error(UserErrorCodeEnum.CAN_NOT_EVALUATE_QUOTA, "芝麻信用不存在");
        }*/
//        JydQuotaRequest request = new JydQuotaRequest()
//                .setUserCode(user.getUserCode())
//                .setRealName(user.getName())
//                .setMobile(user.getMobile())
//                .setIdentityNo(user.getIdentityNo())
//                .setOpenId(userAuthZhimaEntity.getOpenId())
//                .setQuotaTypeEnum(QuotaTypeEnum.YOUQIAN_APP);
//        riskIntegrationService.getQuota(request);
        return new Response<>().ok().putData(true);
    }

    @Override
    public Response<Integer> getQuotaType(String userCode, String productCategory) {
        //获取用户的额度升降集合
        UserQuotaHistoryEntity allQutoaByuserCode = userQuotaHistoryDao.getAllQutoaTypeByuserCode(userCode,productCategory, DateUtil.getDate(new Date(), "yyyy-MM-dd"));
        if (allQutoaByuserCode != null) {
            Integer type = allQutoaByuserCode.getType();
            if (type.equals(PROMOTE_QUOTA.getType())) {
                return new Response<>().ok().putData(PROMOTE_QUOTA.getType());
            } else if (type.equals(KEEP_QUOTA.getType())) {
                return new Response<>().ok().putData(KEEP_QUOTA.getType());
            } else if (type.equals(REDUCE_QUOTA.getType())) {
                return new Response<>().ok().putData(REDUCE_QUOTA.getType());
            } else {
                return Response.error("额度评估失败");
            }
        } else {
            return Response.error("额度评估失败");
        }

    }

    private Boolean fourStepActionComplete(UserInfo userInfo, UserSocialContact socialContact) {
        return //zmCreditActionComplete(userInfo.getUser().getUserCode()) &&
                profileActionComplete(userInfo, socialContact) &&
                        bankActionComplete(userInfo.getUser().getUserCode());
        //carrierActionComplete(userInfo.getUser().getUserCode()) &&
        //!carrierActionExpired(userInfo.getUser().getUserCode());
    }

    private Boolean zmCreditActionComplete(String userCode) {
        Response<CreditAuthResponse> creditAuthResponseResponse = userAuthService.getCreditAuthInfoByUserCode(userCode);
        if (!creditAuthResponseResponse.isSuccess()) {
            throw new ApiErrorException(creditAuthResponseResponse.getMsg());
        }
        CreditAuthResponse creditAuth = creditAuthResponseResponse.getData();
        if (null == creditAuth) {
            return false;
        }
        ZmCredit zmCredit = creditAuth.getZmCredit();
        BankAuth bankAuth = creditAuth.getBankAuth();
        if (null == zmCredit && null == bankAuth) {
            return false;
        }
        return (creditAuth.getAuthorized()
                && (null != zmCredit && StringUtils.isNotEmpty(zmCredit.getOpenId())
                || bankAuth.getBindSuccess()));
    }

    private Boolean profileActionComplete(UserInfo userInfo, UserSocialContact socialContact) {
        return profileBaseInfoComplete(userInfo, socialContact) &&
                profileWorkInfoComplete(userInfo) &&
                profileEmergencyContactInfoComplete(socialContact);
    }

    private Boolean bankActionComplete(String userCode) {
        Response<UserBankInfo> userBankInfoResponse = userBankService.getByUserCode(userCode);
        if (!userBankInfoResponse.isSuccess()) {
            throw new ApiErrorException(userBankInfoResponse.getMsg());
        }

        UserBankInfo userBank = userBankInfoResponse.getData();


        return null != userBank && userBank.getStatus() == 1;
    }

    private Boolean carrierActionComplete(String userCode) {
        Response<UserSocialContact> userSocialContactByUserCode = userContactService.getUserSocialContactByUserCode(userCode);
        return (null != userSocialContactByUserCode.getData().getCarrier());
    }

    private Boolean carrierActionExpired(String userCode) {
        Response<UserSocialContact> userSocialContactByUserCode = userContactService.getUserSocialContactByUserCode(userCode);
        return (DateUtil.diffDateToSecond(new Date(), userSocialContactByUserCode.getData().getCarrier().getGmtDate()) > TimeConsts.ONE_MONTH);
    }

    private Boolean profileBaseInfoComplete(UserInfo userInfo, UserSocialContact socialContact) {

        UserBase userBase = userInfo.getUserBase();
        UserResident resident = userInfo.getUserResident();
        UserContact contact = userInfo.getUserContact();
        if (userBase != null && userBase.getEducation() != null && userBase.getMarriedStatus() != null
                && resident != null && resident.getAddress() != null && resident.getProvinceId() != null
                && resident.getCityId() != null
                && contact != null) {
            return true;
        }
        return false;
    }

    private Boolean profileWorkInfoComplete(UserInfo userInfo) {

        UserWork userWork = userInfo.getUserWork();
        if (null != userWork && userWork.infoComplete()) {
            return true;
        }
        return false;
    }

    private Boolean profileEmergencyContactInfoComplete(UserSocialContact socialContact) {

        UserEmergencyContact userEmergencyContact = socialContact.getUserEmergencyContact();
        if (null != userEmergencyContact &&
                null != userEmergencyContact.getUserFamilyContact() &&
                null != userEmergencyContact.getUserFriendContact()) {
            return true;
        }
        return false;
    }

    private Boolean userZMCreditAuthorized(User user) {

//        Boolean isAuth = riskIntegrationService.zmxyIsAuthorization(user.getIdentityNo(), user.getName());
//        if (!isAuth) {
//            CreditAuthRequest creditAuth = new CreditAuthRequest(user.getUserCode(), CreditAuthTypeEnum.ZM, null);
//            userAuthService.cancelAuth(creditAuth);
//        }
//        return isAuth;
        return false;
    }

}
